home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1993-09-19 | 5.0 KB | 137 lines | [ TEXT/MPAD]
-- This example gives formulas for quadratic and cubic roots and uses the image command to visualize a complex function. Utility functions for complex numbers are at the end of the document. ------------------- quadratic roots --------------- -- Algorithm for real parts of roots is from by W.H. Press, S. Teukolsky et al,"Numerical Recipes". -- Occasionally 4ac << b, so one of the roots is (erroneously) called 0. -- This formulation avoids the problem. -- implemented by David Derbes for MathPad -- Given a quadratic of the form -- a*x^2 + b*x + c = 0 -- with real coefficients, find the (possibly complex) roots. -- Roots are given in the form x + iy. ~ sgn(x) = 1 when x >= 0,-1 otherwise D = (b*b - 4*a*c) -- discriminant x1 = -(b + sgn(b)*sqrt(D))/(2*a) when D >= 0, -b/(2*a) otherwise x2 = c/x1 when D >= 0, -b/(2*a) otherwise y1 = 0 when D >= 0, sqrt(-D)/(2*a) otherwise y2 = -y1 ~ ------------------- cubic roots ------------------- -- Tartaglia's & Cardano's formulae for the roots of a cubic -- from Universal Encyclopaedia of Mathematics -- implemented by David Derbes for MathPad, 8 Sept 1993 -- Given a cubic of the form -- -- a0*x^3 + a1*x^2 + a2*x + a3 = 0 -- -- with real coefficients, find the (possibly complex) roots. c1 = a1/a0 -- "normalize", i.e. make leading coefficient = 1 c2 = a2/a0 c3 = a3/a0 -- discriminant D; if D > 0, one real root; else three real roots -- (at most two distinct real if D = 0) a = c2 - (c1*c1)/3.0 b = (((2.0*c1*c1*c1) - (9.0*c1*c2))/27.0) + c3 D = (b*b/4.0) + (a*a*a/27.0) numRealRoots = 3 when D < 0, 1 otherwise dHalf = sqrt(abs(D)) sgnp = -1 when ((-b/2.0) + dHalf) < 0, 1 otherwise sgnq = -1 when ((-b/2.0) - dHalf) < 0, 1 otherwise p = 0.0 when ((-b/2.0) + dHalf) = 0, sgnp*(abs((-b/2.0) + dHalf))^(1.0/3.0) otherwise q = 0.0 when ((-b/2.0) - dHalf) = 0, sgnq*(abs((-b/2.0) - dHalf))^(1.0/3.0) otherwise s = (-b/2.0)/sqrt(-a*a*a/27.0); theta = acos(s) -- roots of the form x + iy x1 = 2.0*p - (c1/3.0) when numRealRoots = 1 and abs(D) < 1.0e-10, (p+q) - (c1/3.0) when numRealRoots = 1 and abs(D) > 1.0e-10, 2.0*sqrt(-a/3.0)*cos(theta/3.0) - (c1/3.0) otherwise x2 = -p - (c1/3.0) when numRealRoots = 1 and abs(D) < 1.0e-10, -(p+q)/2.0 - (c1/3.0) when numRealRoots = 1 and abs(D) > 1.0e-10, 2.0*sqrt(-a/3.0)*cos((theta/3.0) + 120) - c1/3.0 otherwise x3 = x2 when numRealRoots = 1, 2.0*sqrt(-a/3.0)*cos((theta/3.0) + 240) - c1/3.0 otherwise y1 = 0.0 -- no matter what, must have at least one real root y2 = (p-q)*sqrt(3.0)/2.0 when numRealRoots = 1 and abs(D) > 1.0e-10, 0.0 otherwise y3 = -y2 when numRealRoots = 1 and abs(D) > 1.0e-10, 0.0 otherwise root1 := {x1,y1}:; root2 := {x2,y2}:; root3 := {x3,y3}: ------- Enter the coefficients for the cubic here -------------- -- a0*x^3 + a1*x^2 + a2*x + a3 = 0 a0 = 35; a1 = 15; a2 = -5; a3 = -20 root1:{0.76,0.00} root2:{-0.59,0.64} root3:{-0.59,-0.64} ----------- Check the solution------------ z(x) = a0*Ccube(x) + a1*Csqr(x) + a2*x + {a3,0} -- The complex cubic -- confirm that z(x) is zero at the roots z(root1):{0.00,0.00} z(root2):{0.00,0.00} z(root3):{0.00,0.00} -------- check the solution graphically -- define an array that samples points on the surface of: -- Z = abs(z(x)) vs. X = real(x) , Y = imaginary(x) -- This surface should dip to zero at the roots. (The sampled surface will dip near zero but in general is not sampled exactly at a root). surf[ix,iy] = x:=Cscale(ix,iy), Cabs(z(x)) dim[m,m] -- The index for surf[] runs from 1 to m. Scale the index to get real and imaginary parts ranging from Xmin to Xmax and Ymin to Ymax scale(i,min,max,nsteps) = (i-.5)*(max-min)/nsteps+min Cscale(ix,iy) = {scale(ix,Xmin,Xmax,m), scale(iy,Ymin,Ymax,m)} m=12; -- surface is sampled on an m by m grid Xmin = -1; Xmax = 1 Ymin = -1; Ymax = 1 Zmin = 0; Zmax = 50 image surf -- show image of the surface plot {root1,root2,root3} -- show locations of roots plot z({X,0})[1]/Zmax -- plot the real part of z for real x -- This should be zero at real roots. On the plotted surface, real roots are located along y=0 so the real cubic plotted in this way should pass though its real roots. plot 0 -------------------------------------------------------------------- ----------- utility functions for complex numbers ------ -- Arrays can be used to represent complex numbers. Addition, subtraction and multiplication by a real can be done directly. The following functions implement other basic operations on complex numbers. Note that a real number r must be written as {r,0}. Cabs(A) = sqrt(A[1]^2+A[2]^2) Cmult(A,B) = {A[1]*B[1]-A[2]*B[2],A[2]*B[1]+A[1]*B[2]} Csqr(A) = {A[1]*A[1]-A[2]*A[2],2*A[1]*A[2]} Ccube(A) = Cmult(A,Csqr(A)) -- (the following were not used in this example) Cdiv(A,B)={(B[1]*A[1]+B[2]*A[2])/(B[1]^2+B[2]^2), (B[1]*A[2]-B[2]*A[1])/(B[1]^2+B[2]^2)} Conj(A) = {A[1],-A[2]} Carg(A) = 0 when A[1]=0 and A[2]=0, atan(A[2]/A[1]) when A[1]>=0, atan(A[2]/A[1])+180 when A[2]>=0, atan(A[2]/A[1])-180